#ifndef QSQLCONTROL_H
#define QSQLCONTROL_H

#include "SQLBase.h"
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <type_traits>
#include <QDebug>
#include <QSqlResult>
#include <QSqlRecord>
#include <typeinfo>

class QSQLControl : public SQLBase
{
public:
    QSQLControl();

    virtual void ReLoad() override;
    virtual void ConnectToDB() override;
    virtual void DisConnect() override;
    virtual void Exec(std::string) override;
    virtual void insert(QString ,QStringList) override;
    virtual QVariantList Get(std::string) override;

    virtual QVariantList Get(std::string,std::initializer_list<std::string> ,std::initializer_list<std::string> ) override;


    QSqlDatabase _Qdb;



//    /**
//     * @brief prepare
//     * @param [0] query
//     * INSERT INTO FRAMEPOS (`pos`)VALUES('?')
//     * "STD::STRING"
//     */
//    template< typename ... Args>
//    void prepare(std::string _query,Args...  mArgs){
//        QSqlQuery query(_Qdb);
//        query.prepare(_query.data());
//        auto a = std::forward_as_tuple(mArgs...);
//        __tupleEach::each_tuple(
//        [&query](auto a, std::size_t idx)
//        {
//            query.addBindValue((QVariant)a);
//        }, a);

//        query.exec();
//        query.lastError().text().isEmpty() ? undo() : pushExp(MU_Messages::SQL,MU_EXPS::EXP_SQL_WRITE,MU_ERROR_MODULE_SQL,DateTime::getFullTime()) ;
//    }

    template<typename T>
    static QVariant getValue(T t){
        auto identity = [](decltype(t) t){
            QVariant h;
            h.setValue(t);
            return h;};
        return identity(t);
    }


    /**
     * @details 动态可变参数插入
     * @author 张鲜祥
     */
    template< typename... Args>
    void prepare(std::string _query,Args...  mArgs){
        QSqlQuery query(_Qdb);
        query.prepare(_query.data());
        auto a = std::forward_as_tuple(mArgs...);
        std::apply([&query,this](auto&&... args){
            auto getValue = [](auto t)->QVariant{   QVariant h;  h.setValue(t); return h;};
            ((query.addBindValue(getValue(args))), ...);
        },a);

        query.exec();
        query.lastError().text().isEmpty() ? undo() :
              pushExp(MU_Messages::SQL,MU_EXPS::EXP_SQL_WRITE,MU_ERROR_MODULE_SQL,DateTime::getFullTime()) ;
    }



//    template< typename... Args>
//    void prepare(std::string _query,Args...  mArgs){
//        QSqlQuery query(_Qdb);
//        auto fn = [](){};
//        query.prepare(_query.data());
//        auto a = std::forward_as_tuple(mArgs...);
//        std::apply([&query](auto&&... args)
//        { ((std::cout << typeid (args).name()  << "\t" << args << std::endl ), ...); },
//                        a);

//        query.exec();
//        query.lastError().text().isEmpty() ? undo() :
//              pushExp(MU_Messages::SQL,MU_EXPS::EXP_SQL_WRITE,MU_ERROR_MODULE_SQL,DateTime::getFullTime()) ;
//    }

//    template< class... Args>
//    void prepare(std::string _query,const std::tuple<Args...> &a){
//        auto result = std::async(std::launch::async,[=](std::string q,const std::tuple<Args...> &a){
//            QSqlQuery query(_Qdb);
//            query.prepare(q.data());
//            __tupleEach::each_tuple(
//            [&query](auto a, std::size_t idx)
//            {
//                query.addBindValue((QVariant)a);
//            }, a);

//            query.exec();
//            return query.lastError().text();
//        },_query,a);
//        result.get().isEmpty() ? undo() : pushExp(MU_Messages::SQL,MU_EXPS::EXP_SQL_WRITE,MU_ERROR_MODULE_SQL,DateTime::getFullTime()) ;
//    }
};

#endif // QSQLCONTROL_H
